package controller

import (
	"aqchain/pkg/entity"
	"aqchain/pkg/log"
	"aqchain/pkg/model"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"net/http"
)

// GetAuction 获取拍卖信息
func (c *Controller) GetAuction(ctx *gin.Context) {
	// 参数绑定
	var params entity.GetAuctionUri
	err := ctx.BindUri(&params)
	if err != nil {
		log.Logger.Debug("error", zap.Error(err), zap.String("code", errParams.Error()))
		ctx.JSON(http.StatusBadRequest, ErrorResponse(errParams))
		return
	}
	// 检查作品
	var itemRecord model.Item
	err = c.db.Where(model.Item{DCI: params.DCI}).First(&itemRecord).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			log.Logger.Debug("error", zap.Error(err), zap.String("code", errItemNotExist.Error()))
			ctx.JSON(http.StatusBadRequest, ErrorResponse(errItemNotExist))
			return
		} else {
			log.Logger.Debug("error", zap.Error(err), zap.String("code", errDBError.Error()))
			ctx.JSON(http.StatusInternalServerError, ErrorResponse(errDBError))
			return
		}
	}
	// 获取指定交易状态
	var record model.Auction
	err = c.db.Where(model.Auction{DCI: params.DCI}).First(&record).Error
	if err != nil {
		log.Logger.Debug("error", zap.Error(err), zap.String("code", errAuctionNotExist.Error()))
		ctx.JSON(http.StatusOK, ErrorResponse(errAuctionNotExist))
		return
	}
	if err != nil {
		return
	}
	data := entity.Auction{
		DCI:           record.DCI,
		Seller:        record.Seller,
		BlockNumber:   record.BlockNumber,
		Deadline:      record.Deadline,
		ReservePrice:  record.ReservePrice,
		HighestBid:    record.HighestBid,
		HighestBidder: record.HighestBidder,
	}
	ctx.JSON(http.StatusOK, SuccessResponse(data))
}

// GetAuctions 获取拍卖信息集合
func (c *Controller) GetAuctions(ctx *gin.Context) {
	// 参数绑定
	var params entity.GetAuctionsQuery
	err := ctx.BindQuery(&params)
	if err != nil {
		log.Logger.Debug("error", zap.Error(err), zap.String("code", errParams.Error()))
		ctx.JSON(http.StatusBadRequest, ErrorResponse(errParams))
		return
	}
	// 查询交易状态集合 用到了左连接 效率未知
	var records []entity.Auction
	db := c.db.Select(
		"items.dci as dci", "seller", "block_number", "deadline", "reserve_price", "highest_bid", "highest_bidder",
		"items.name as name", "items.description as description", "items.category as category", "block_time").Joins("left join items on auctions.dci = items.dci")

	//按照作品创建时间查询
	if params.IsBlockTimeSearch() {
		begin, end, err := params.Convert()
		if err != nil {
			log.Logger.Debug("error", zap.Error(err), zap.String("code", err.Error()))
			ctx.JSON(http.StatusBadRequest, ErrorResponse(err))
		}
		db = db.Where("auctions.block_time between ? and ?", begin, end)
	}

	//按照作品名称去查找
	if params.IsNameSearch() {
		db = db.Where("name like ?", fmt.Sprintf("%s%s%s", "%", params.Name, "%"))
	}
	//按照作品类型去查找
	if params.IsItemTypeSearch() {
		db = db.Where("category = ?", params.Category)
	}

	if params.IsPagination() {
		db = db.Limit(int(params.PageSize)).Offset(int((params.Current - 1) * params.PageSize))
	}
	err = db.Where(model.Auction{DCI: params.DCI, Seller: params.Seller}).Find(&records).Error
	if err != nil {
		log.Logger.Debug("error", zap.Error(err), zap.String("code", errDBError.Error()))
		ctx.JSON(http.StatusInternalServerError, ErrorResponse(errDBError))
		return
	}
	ctx.JSON(http.StatusOK, SuccessResponse(records))
}

// GetAuctionEvents 获取拍卖合约事件历史记录
func (c *Controller) GetAuctionEvents(ctx *gin.Context) {
	// 参数绑定
	var params entity.GetAuctionEventsQuery
	err := ctx.BindQuery(&params)
	if err != nil {
		log.Logger.Debug("error", zap.Error(err), zap.String("code", errParams.Error()))
		ctx.JSON(http.StatusBadRequest, ErrorResponse(err))
		return
	}
	var events []entity.AuctionEvent
	// 使用Model函数确认查询的表
	db := c.db.Model(&model.AuctionEvent{})
	if params.IsPagination() {
		db = db.Limit(int(params.PageSize)).Offset(int((params.Current - 1) * params.PageSize))
	}
	db = db.Where(&model.AuctionEvent{DCI: params.DCI, From: params.Seller, EventName: params.EventName})
	if params.BlockNumber > 0 {
		db = db.Where("blockNumber>?", params.BlockNumber)
	}
	err = db.Find(&events).Error
	if err != nil {
		log.Logger.Debug("error", zap.Error(err), zap.String("code", errDBError.Error()))
		ctx.JSON(http.StatusInternalServerError, ErrorResponse(errDBError))
		return
	}
	ctx.JSON(http.StatusOK, SuccessResponse(events))
}
